大家好!今天要來介紹模組(Module),這裡的模組和遊戲中常見的模組意思不一樣,TypeScript(TS)的模組可以想成是將具有特定功能的程式碼拆分到不同檔案中,再透過export 和import讓不同檔案之間共享需要使用的內容,遊戲模組更傾向於遊戲外的擴充包。
當一個專案功能愈來愈多,程式碼也逐漸變多,除了難以管理、維護外,所有程式碼都集中在同一個檔案時,也容易遇到命名管理,團隊合作困難等問題。因此,我們需要有組織的分類專案的功能,將它們拆成各自獨立的檔案,再用export/import,提高程式的可讀性和可維護性,團隊也能更好的分配各自的工作,不用擠在同個檔案下開發,進而導致程式發生衝突。
export導出當外部檔案要使用某個模組時,我們能透過export將模組導出,讓外部檔案存取。沒有加 export的變數、函式、型別、或class,預設只能在自己的檔案裡面使用,外部檔案無法使用這些內容。
//export範例:
//math.ts
const secretNumber = 42; //沒有export的變數,只能在math.ts內部使用
//有export的函式,其他檔案就能引入使用
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
除此之外,型別、介面、class也能使用export:
//type.ts
export type User = {
id: number;
name: string;
};
export interface Product {
id: number;
price: number;
}
import導入既然有導出,那一定會有與之相對的導入import,賣家把包裹送出去,那一定會有接收包裹的買家嘛!import就是接收這些模組,把檔案帶到內部使用的語法。
// main.ts
import { add, subtract } from './math';
//import內要放入與export相同的名稱,後面的from代表確切的路徑位置
console.log(add(1, 2)); //輸出:3
console.log(subtract(5, 2)); //輸出:3
介紹完最基本的export和import後,接著來認識具名匯出。具名匯出指的是為導出的物件、型別指定名稱,像方才在export裡舉例的add和subtract都是具名匯出的例子。而在import的時候,import必須跟期望引入的export名稱相對應。
// utils.ts
export const PI = 3.14159;
export function double(n: number): number {
return n * 2;
}
export function triple(n: number): number {
return n * 3;
}
如果匯入的名稱與目前檔案中的其他名稱衝突,或想讓名稱更符合目前檔案的語意,可以使用 as 重新命名:
import { double as timesTwo } from './utils';
console.log(timesTwo(5)); // 10
如果想將某個模組的多個具名匯出一次引入,也可以使用import * as,並透過指定的名稱存取:
import * as MathUtils from './utils';
console.log(MathUtils.PI);
console.log(MathUtils.double(3));
除了具名匯出,另一種常見的匯出是預設匯出,與具名匯出不同,一個模組只能有一個 default export,引入的時候,也不必與export的名稱對應,隨便取名即可,與具名匯出不同,預設匯出在import時不需要使用大括號,而且匯入端可以自行決定名稱。
//default export範例:
//user.ts
export default function getUserName() {
return "Alice";
}
import時:
import userName from "./user";
//引入時,不需要括號,名字也能隨意取,但是路徑一定要一致
console.log(UserName());
兩種匯出的方法有明顯的差別,在這邊補個表格比較:
| 具名匯出(Named Export) | 預設匯出(Default Export) | |
|---|---|---|
| 一個檔案能擁有的數量 | 多個 | 一個 |
| 引入名稱規範 | 需和export相同/使用as改名 | 可以更改名稱 |
| 適用場合 | 擁有多功能的專案 | 只有一個核心功能的專案 |
import type是TS有,JavaScript(JS)沒有的語法。顧名思義,這個import只會引入型別,常見的應用就是在編譯階段做型別檢查,因為這些內容只用於型別檢查,所以不需要在JavaScript的執行階段保留這個import。
// types.ts
export interface User {
id: number;
name: string;
}
// app.ts
import type { User } from './types';
function printUser(user: User) {
console.log(user.name);
}
因為import type明確表示這是型別匯入,TypeScript可以知道它不需要在執行階段保留這個匯入,程式碼的可讀性也會更好。
Module在剛學程式時不太會用到,然而當專案逐漸變大時,我們就得善用它,除了方便管理,也能讓程式看上去更為簡潔、有結構。今天的內容就到這邊,我們明天見!